// Copyright 2007 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package lichen.typecoercer;

import javax.persistence.Entity;

import lichen.entities.PersistModel;

import org.apache.tapestry.internal.services.ClassNameLocator;
import org.apache.tapestry.ioc.Configuration;
import org.apache.tapestry.ioc.annotations.InjectService;
import org.apache.tapestry.ioc.services.Coercion;
import org.apache.tapestry.ioc.services.CoercionTuple;
import org.hibernate.Session;

/**
 * 定义一些 TypeCoercer
 * @author Jun Tsai
 * @version $Revision$
 * @since 0.0.3
 */
public class TypeCoercerModule {
	/**
	 * 对tapestry核心的TypeCorerce进行扩展，实现了PO到字符串的转换.
	 * @author <a href="mailto:jun.tsai@gmail.com">Jun Tsai</a>
	 * @version $Revision: 28 $
	 * @since 0.0.1
	 */
	public static class GenericCoercion<PO extends PersistModel> implements Coercion<String,PO>{
		private Class<PO> clazz;
		private Session _session;
		public GenericCoercion(Session session,Class<PO> clazz){
			this._session=session;
			this.clazz=clazz;
		}
		@SuppressWarnings("unchecked")
		public PO coerce(String input) {
			return (PO) _session.load(clazz, input);
		}
		
	}
	
	/**
	 * 构建TypeCoercer
	 * @param configuration 配置.
	 * @param session hibernate session.
	 * @param classNameLocator class name locator.
	 */
	@SuppressWarnings("unchecked")
	public static void contributeTypeCoercer(
			Configuration<CoercionTuple> configuration,
			@InjectService("Session")
			final Session session,@InjectService("ClassNameLocator")
		    ClassNameLocator classNameLocator) {
		
		String packageName="lichen.entities";
		ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
		 for (String className : classNameLocator.locateClassNames(packageName))
         {
             try
             {
                 Class<?> entityClass = contextClassLoader.loadClass(className);
                 if(entityClass.isAnnotationPresent(Entity.class)){//仅仅处理有Entity注释的类
                	 configuration.add(new CoercionTuple(String.class,
                		 entityClass, new GenericCoercion(session,entityClass)));
                 }
             }
             catch (ClassNotFoundException ex)
             {
                 throw new RuntimeException(ex);
             }
         }
		classNameLocator.locateClassNames(packageName);
		Coercion<PersistModel, String> po2String = new Coercion<PersistModel, String>() {
			public String coerce(final PersistModel input) {
				return session.getIdentifier(input).toString();
//				return input.getId();
			}
		};

		configuration.add(new CoercionTuple<PersistModel, String>(
				PersistModel.class, String.class, po2String));
		
	}

}
